package models.tasks

import java.sql.Timestamp
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

import javax.inject.Inject
import play.api.Logging
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import services.OutStockPostParameters
import slick.jdbc.JdbcProfile

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext}

class JobExecutionsRepository @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit executionContext: ExecutionContext)
  extends HasDatabaseConfigProvider[JdbcProfile] with Logging {

  import profile.api._

  private class JobsExecTable(tag: Tag) extends Table[JobExecution](tag, "TASKS_JOBEXEC") {
    def id = column[Option[Int]]("id".toUpperCase)

    def status = column[Int]("status".toUpperCase)

    def started = column[Option[Timestamp]]("started".toUpperCase)

    def finished = column[Option[Timestamp]]("finished".toUpperCase)

    def exception = column[Option[String]]("exception".toUpperCase)

    def traceback = column[Option[String]]("traceback".toUpperCase)

    def job_id = column[String]("job_id".toUpperCase)

    def name = column[String]("name".toUpperCase)

    def * = (id, status, started, finished, exception, traceback, job_id, name).<>((JobExecution.apply _).tupled, JobExecution.unapply)
  }

  private val jobExec = TableQuery[JobsExecTable]

  def create(exec: JobExecution) = db.run(jobExec returning jobExec.map(_.id) += exec)

  def update(id: Option[Int], status: Int, finished: Option[Timestamp] = None, exception: Option[String] = None, traceback: Option[String] = None) = db.run {
    jobExec.filter(_.id === id).map(f => (f.status, f.finished, f.exception, f.traceback)).update((status, finished, exception, traceback))
  }

  def delete(id: Option[Int] = None, started: Option[Timestamp] = None, finished: Option[Timestamp] = None, name: String = "") = db.run {
    if (id.nonEmpty){
      jobExec.filterOpt(id)(_.id === _).delete
    }else{
      jobExec
        .filterIf(name.nonEmpty)(_.name === name)
        .filterOpt(started)(_.started >= _)
        .filterOpt(finished)(_.finished <= _)
        .delete
    }
  }

  def findAll(p: OutStockPostParameters) = {
    val dtformat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
    val offset = p.limit * p.page
    val jobExecName = p.p1
    val f = if (p.sdate.length < 40) {
      jobExec
        .filterIf(jobExecName != "all")(_.name === jobExecName)
        .filterIf(p.status != -1)(_.status === p.status)
    } else {
      val datestart = Option(Timestamp.valueOf(LocalDateTime.parse(p.sdate.substring(0, 19))))
      val dateend = Option(Timestamp.valueOf(LocalDateTime.parse(p.sdate.substring(22))))
      jobExec
        .filterIf(jobExecName != "all")(_.name === jobExecName)
        .filterIf(p.status != -1)(_.status === p.status)
        .filterOpt(datestart)(_.started >= _)
        .filterOpt(dateend)(_.started <= _)
    }
    val res = f.sortBy(_.id).drop(offset).take(p.limit).map(f => f).result
    val total = f.length.result
    db.run(res).zip(db.run(total))
  }

  def findAllName = db.run {
    jobExec.map(_.name).distinct.result
  }

}
